import { Component, OnInit, Inject, TemplateRef, ViewChild, OnChanges, OnDestroy } from '@angular/core'

import { IBaseInfoColumn } from '@shared/interfaces/baseInfo'
import { DataService } from '@shared/services/data.service'
import { Terminal, ITerminalUpdateRequest, IEmvPans } from '@shared/interfaces/terminal'
import { PageService } from '@shared/services/page.service'
import { ETabScrollStatus, EPaymentBrand, ECustomAcl } from '@shared/enums'
import { deepCopy } from '@delon/util'
import { Subject } from 'rxjs'
import { StoreService } from 'app/routes/store/store.service'
import { TerminalService } from '../../terminal.abstract.service'
import { NzMessageService, NzNotificationService } from 'ng-zorro-antd'
import { HttpErrorResponse } from '@angular/common/http'
import { I18NService } from '@core'
import { CustomACLService } from '@shared/services/acl.service'

@Component({
  selector: 'app-terminal-detail-tab-transaction',
  templateUrl: './tab-transaction.component.html',
  styles: ['./tab-transaction.component.less'],
})
export class TerminalDetailTabTransactionComponent implements OnInit, OnDestroy {
  @ViewChild('operate') operate: TemplateRef<void>
  @ViewChild('isFixedTpl') isFixedTpl: TemplateRef<void>
  @ViewChild('fixedInputTpl') fixedInputTpl: TemplateRef<void>

  funcIsEdit = false

  tradeColumns: IBaseInfoColumn[][] = []
  funcColumns: IBaseInfoColumn[] = [] // 终端功能
  terminal: Terminal
  copyTerminal: Terminal

  isAmountFixed$: Subject<boolean> = new Subject()
  loading = true

  constructor(
    public dataService: DataService,
    public terminalService: TerminalService,
    public msg: NzMessageService,
    public notification: NzNotificationService,
    private pageService: PageService,
    private i18n: I18NService,
    private storeService: StoreService,
    private customACLService: CustomACLService,
  ) {}

  ngOnInit() {
    this.dataService.terminal$.value$.subscribe(terminal => {
      this.terminal = terminal
      this.copyTerminal = deepCopy(terminal)
      this.initTradeColumns()
      this.initFuncColumns()
    })
    this.pageService.setTabScrollStatus(ETabScrollStatus.Scroll)
  }

  ngOnDestroy() {
    this.customACLService.removeACLAbility(ECustomAcl.TerminalPANCanUPI)
    this.customACLService.removeACLAbility(ECustomAcl.TerminalPANCanVIS)
    this.customACLService.removeACLAbility(ECustomAcl.TerminalPANCanMCC)
    this.customACLService.removeACLAbility(ECustomAcl.TerminalPANCanFPS)
  }

  initTradeColumns(): void {
    const { emvPans, common } = this.terminal
    const { intStoreCode } = common
    const firstColumns = this.initFirstColumns(emvPans)
    const secondColumns = this.initSecondColumns(emvPans)

    this.storeService.getOne(intStoreCode).subscribe(storeFull => {
      const { qrChannels } = storeFull
      const canUPI = !!qrChannels.find(channel => channel.chanCode === EPaymentBrand.UPI)
      const canVIS = !!qrChannels.find(channel => channel.chanCode === EPaymentBrand.Visa)
      const canMCC = !!qrChannels.find(channel => channel.chanCode === EPaymentBrand.MasterCard)
      const canFPS = !!qrChannels.find(channel => channel.chanCode === EPaymentBrand.FPS)
      this.addPanACLAbility(canUPI, EPaymentBrand.UPI)
      this.addPanACLAbility(canVIS, EPaymentBrand.Visa)
      this.addPanACLAbility(canMCC, EPaymentBrand.MasterCard)
      this.addPanACLAbility(canFPS, EPaymentBrand.FPS)
      if (canUPI || canVIS) {
        this.tradeColumns.push(firstColumns)
      }
      if (canMCC || canFPS) {
        this.tradeColumns.push(secondColumns)
      }
      this.loading = false
    })
  }

  initFirstColumns(emvPans: IEmvPans): IBaseInfoColumn[] {
    return [
      {
        span: 12,
        index: 'emvPans.upiPan',
        label: 'UPI PAN',
        value: emvPans && emvPans.upiPan ? emvPans.upiPan : this.trans('GENERAL.INFO.NONE'),
        acl: [ECustomAcl.TerminalPANCanUPI],
      },
      {
        span: 12,
        index: 'emvPans.visPan',
        label: 'VISA PAN',
        value: emvPans && emvPans.visPan !== '' ? emvPans.visPan : this.trans('GENERAL.INFO.NONE'),
        acl: [ECustomAcl.TerminalPANCanVIS],
      },
    ]
  }

  initSecondColumns(emvPans: IEmvPans): IBaseInfoColumn[] {
    return [
      {
        span: 12,
        index: 'emvPans.mccPan',
        label: 'MasterCard PAN',
        value: emvPans && emvPans.mccPan !== '' ? emvPans.mccPan : this.trans('GENERAL.INFO.NONE'),
        acl: [ECustomAcl.TerminalPANCanMCC],
      },
      {
        span: 12,
        index: 'emvPans.fpsPan',
        label: 'FPS PAN',
        value: emvPans && emvPans.fpsPan !== '' ? emvPans.fpsPan : this.trans('GENERAL.INFO.NONE'),
        acl: [ECustomAcl.TerminalPANCanFPS],
      },
    ]
  }

  addPanACLAbility(can: boolean, paymentBrand: EPaymentBrand): void {
    if (!can) return
    switch (paymentBrand) {
      case EPaymentBrand.UPI:
        this.customACLService.addACLAbility(ECustomAcl.TerminalPANCanUPI)
        break
      case EPaymentBrand.Visa:
        this.customACLService.addACLAbility(ECustomAcl.TerminalPANCanVIS)
        break
      case EPaymentBrand.MasterCard:
        this.customACLService.addACLAbility(ECustomAcl.TerminalPANCanMCC)
        break
      case EPaymentBrand.FPS:
        this.customACLService.addACLAbility(ECustomAcl.TerminalPANCanFPS)
        break
    }
  }

  initFuncColumns(): void {
    const { isAmountFixed, fixedAmt } = this.copyTerminal.qr
    const { transCurr } = this.copyTerminal.common
    this.funcColumns = [
      {
        span: 10,
        index: 'qr.isAmountFixed',
        label: 'GENERAL.INFO.FIXED_AMT_QR_CODE_SUPPORTED',
        labelI18n: 'GENERAL.INFO.FIXED_AMT_QR_CODE_SUPPORTED',
        value: isAmountFixed ? this.trans('GENERAL.INFO.YES') : this.trans('GENERAL.INFO.NO'),
        template: this.isFixedTpl,
      },
      {
        span: 10,
        index: 'qr.fixedAmt',
        label: 'GENERAL.INFO.FIXED_AMT_OF_QR_CODE',
        labelI18n: 'GENERAL.INFO.FIXED_AMT_OF_QR_CODE',
        value: fixedAmt,
        displayValue: (fixedAmt === '' ? '0' : fixedAmt) + transCurr,
        asyncDisEditable: this.isAmountFixed$,
      },
      {
        span: 4,
        label: 'GENERAL.INFO.OPERATION',
        labelI18n: 'GENERAL.INFO.OPERATION',
        template: this.operate,
        operate: true,
      },
    ]
  }

  isAmountFixedChange(is): void {
    this.isAmountFixed$.next(!is)
  }

  edit(): void {
    this.isAmountFixed$.next(!this.terminal.qr.isAmountFixed)
    this.funcIsEdit = true
  }

  cancel(): void {
    this.funcIsEdit = false
    this.resetCopyValue()
    this.initFuncColumns()
  }

  submit(): void {
    const { intStoreCode, termCode } = this.terminal.common
    this.funcIsEdit = false
    const updatedQrData = this.update(this.funcColumns, this.copyTerminal)
    const dataToUpdate = this.genDataToUpdate(updatedQrData)
    this.terminalService.update(dataToUpdate, intStoreCode, termCode).subscribe(
      isSuccess => {
        if (isSuccess) {
          this.msg.success(this.trans('GENERAL.NOTIFICATION.UPDATE_SUCCESS'))
        }
      },
      (err: HttpErrorResponse) => {
        this.notification.error(`this.trans('GENERAL.NOTIFICATION.UPDATE_FAIL')`, err.error)
      },
    )
    this.resetCopyValue()
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private genDataToUpdate(updatedQrData): ITerminalUpdateRequest {
    const { version, common } = this.terminal
    return {
      version,
      common: {
        remark: common.remark,
        termVendar: common.termVendar,
      },
      qr: {
        isAmountFixed: updatedQrData.isAmountFixed,
        fixedAmt: updatedQrData.fixedAmt,
      },
    }
  }

  private update(arr: IBaseInfoColumn[], detailData) {
    let value = detailData
    arr.forEach(column => {
      /* 如果是传模版进去，则不做赋值操作，会覆盖 */
      if (column.template) return
      const index = column.index as string
      const keys = index.split('.')
      keys.forEach((key, i) => {
        if (i === keys.length - 1) {
          return
        }
        value = value[key]
      })
      value[keys[keys.length - 1]] = column.value
    })
    return value
  }

  private resetCopyValue() {
    this.copyTerminal = deepCopy(this.terminal)
  }
}
